package com.card.service.system;

import java.util.List;
import java.util.Random;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSONObject;
import com.card.consts.ScoreSourceConsts;
import com.card.consts.SystemConsts;
import com.card.entity.manager.User;
import com.card.entity.manager.UserScore;
import com.card.redis.JedisService;
import com.card.repository.IUserRepository;
import com.card.repository.IUserScoreRepository;
import com.card.result.Result;
import com.card.util.ValidUtil;
import com.card.vo.ForgetPassword;
import com.card.vo.MobileRegister;

/**
 * ClassName: RegisterService <br/>
 * Function: 注册service. <br/>
 * date: 2018年10月16日 上午9:37:48 <br/>
 * 
 * @author lishuai11
 * @version
 * @since JDK 1.8
 */
@Service("registerServie")
public class RegisterService {

	private static final Logger logger = LoggerFactory.getLogger(RegisterService.class);

	@Autowired
	private JedisService jedisService;

	@Autowired
	private SmsService smsService;

	@Autowired
	private IUserRepository userRepository;

	@Autowired
	private IUserScoreRepository userScoreRepository;

	@Value("${sms.expire}")
	private int expire;

	/**
	 * 
	 * code:(获取验证码). <br/>
	 * 
	 * @author lishuai11
	 * @param mobile
	 * @return
	 * @since JDK 1.8
	 */
	public Result code(String mobile) {
		try {
			if (jedisService.isExist(mobile)) {
				return Result.fail(Result.CLIENT_ERROR, "请于1分钟后发送");
			}
			String code = code();
			int expire = redisCache(mobile, code);
			if (smsService.sendSms(mobile, code)) {
				JSONObject jsonObject = new JSONObject();
				jsonObject.put("mobile", mobile);
				jsonObject.put("expire", expire);
				return Result.success("发送成功", jsonObject);
			} else {
				jedisService.delete(mobile);
				return Result.fail(Result.SERVER_ERROR, "短信发送失败");
			}
		} catch (Exception e) {
			logger.error("RegisterService.code()方法异常{}:{}", e.getMessage(), e);
			return Result.fail(Result.SERVER_ERROR, "服务器异常");
		}
	}

	/**
	 * 
	 * mobileRegister:(手机号码注册). <br/>
	 * 
	 * @author lishuai11
	 * @param mobileRegister
	 * @return
	 * @since JDK 1.8
	 */
	@Transactional
	public Result mobileRegister(MobileRegister mobileRegister) {
		try {
			// ①：判断验证码是否超时
			if (!jedisService.isExist(mobileRegister.getMobile())) {
				return Result.fail(Result.CLIENT_ERROR, "验证码超时");
			}
			// ②：判断验证码是否正确
			String param = jedisService.get(mobileRegister.getMobile());
			if (!param.equals(mobileRegister.getCode())) {
				return Result.fail(Result.CLIENT_ERROR, "验证码错误");
			}
			synchronized (SystemConsts.CLASS_LOCK) {
				String inviteCode = mobileRegister.getInviteCode();
				User user = findByMobile(mobileRegister.getMobile());
				if (user != null) {
					return Result.fail(Result.CLIENT_ERROR, "用户名已注册");
				}
				if (!StringUtils.isBlank(inviteCode)) {
					if (!ValidUtil.codeIsValid(inviteCode)) {
						return Result.fail(Result.CLIENT_ERROR, "非法邀请码");
					}
					User scoreUser = findByInviteCode(inviteCode);
					if (scoreUser == null) {
						return Result.fail(Result.CLIENT_ERROR, "非法邀请码");
					}
					UserScore userScore = new UserScore(scoreUser.getUserId(), ScoreSourceConsts.ACTIVITY_REGISTER,
							ScoreSourceConsts.ACTIVITY_REGISTER_SCORE, true);
					userScoreRepository.save(userScore);
					scoreUser.setTotalScore(scoreUser.getTotalScore() + ScoreSourceConsts.ACTIVITY_REGISTER_SCORE);
					userRepository.save(scoreUser);
					// ③：信息校验成功，注册成功
					String password = DigestUtils.md5Hex(mobileRegister.getPassword());
					user = new User(mobileRegister.getMobile(), password);
					user = userRepository.save(user);
					jedisService.delete(mobileRegister.getMobile());
					return Result.success("注册成功", user);
				} else {
					// ③：信息校验成功，注册成功
					String password = DigestUtils.md5Hex(mobileRegister.getPassword());
					user = new User(mobileRegister.getMobile(), password);
					user = userRepository.save(user);
					jedisService.delete(mobileRegister.getMobile());
					return Result.success("注册成功", user);
				}
			}
		} catch (Exception e) {
			logger.error("RegisterService.mobileRegister()方法异常{}:{}", e.getMessage(), e);
			return Result.fail(Result.SERVER_ERROR, "服务器异常");
		}
	}

	public Result forgetPassword(ForgetPassword forgetPassword) {
		synchronized (this) {
			try {
				// ①：判断验证码是否超时
				if (!jedisService.isExist(forgetPassword.getMobile())) {
					return Result.fail(Result.CLIENT_ERROR, "验证码超时");
				}
				// ②：判断验证码是否正确
				String param = jedisService.get(forgetPassword.getMobile());
				if (!param.equals(forgetPassword.getCode())) {
					return Result.fail(Result.CLIENT_ERROR, "验证码错误");
				}
				User user = findByMobile(forgetPassword.getMobile());
				if (user == null) {
					return Result.fail(Result.CLIENT_ERROR, "用户不存在");
				} else {
					String password = DigestUtils.md5Hex(forgetPassword.getSecondPassword());
					if (user.getPassword().equals(password)) {
						return Result.fail(Result.CLIENT_ERROR, "密码与之前一致");
					}
					user.setPassword(password);
					user = userRepository.save(user);
					jedisService.delete(forgetPassword.getMobile());
					return Result.success("新密码设置成功");
				}
			} catch (Exception e) {
				logger.error("RegisterService.forgetPassword()方法异常{}:{}", e.getMessage(), e);
				return Result.fail(Result.SERVER_ERROR, "服务器异常");
			}
		}
	}

	/**
	 * 
	 * code:(生成验证码). <br/>
	 * 
	 * @author lishuai8
	 * @return
	 * @since JDK 1.8
	 */
	private String code() {
		Random random = new Random();
		StringBuilder builder = new StringBuilder();
		for (int i = 0; i < 6; i++) {
			builder.append(random.nextInt(10));
		}
		return builder.toString();
	}

	/**
	 * 
	 * redisCache:(缓存验证码). <br/>
	 * 
	 * @author lishuai11
	 * @param mobile
	 * @param code
	 * @return
	 * @throws Exception
	 * @since JDK 1.8
	 */
	private int redisCache(String mobile, String code) throws Exception {
		String key = mobile;
		int time = expire;
		jedisService.setex(key, time, code);
		return time;
	}

	private User findByMobile(String mobile) {
		List<User> users = userRepository.findByMobile(mobile);
		if (users != null && !users.isEmpty()) {
			return users.get(0);
		}
		return null;
	}

	public User findByInviteCode(String inviteCode) {
		List<User> list = userRepository.findByInviteCode(inviteCode);
		if (list != null && !list.isEmpty()) {
			return list.get(0);
		}
		return null;
	}
}
